package com.visionforge.sdk;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.Base64;
import java.util.UUID;

/**
 * VisionForge SDK主类，实现与Python SDK相同的功能
 */
public class VisionForgeSDK {
    // 接口地址
    private static final String API_URL = "http://14.103.236.44:18001/api/ai/detect";
    // 备用接口地址
    private static final String API_URL_BACKUP = "http://116.204.115.87:19001/api/ai/detect";
    
    private final HttpClient httpClient;
    private final ObjectMapper objectMapper;
    private final String apiUrl;

    /**
     * 默认构造函数，使用主API地址
     */
    public VisionForgeSDK() {
        this(API_URL);
    }

    /**
     * 构造函数，允许指定API地址
     * @param apiUrl API地址
     */
    public VisionForgeSDK(String apiUrl) {
        this.apiUrl = apiUrl;
        this.httpClient = HttpClient.newBuilder()
                .connectTimeout(Duration.ofSeconds(30))
                .build();
        
        this.objectMapper = new ObjectMapper()
                .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    }

    /**
     * 上传图片到AI检测接口并获取检测结果
     * @param imagePath 图片文件路径
     * @param modelCode 模型编码
     * @return 检测结果对象
     */
    public DetectionResult uploadImageForDetection(String imagePath, String modelCode) {
        File imageFile = new File(imagePath);
        if (!imageFile.exists() || !imageFile.isFile()) {
            System.out.println("错误: 图片文件不存在 - " + imagePath);
            return null;
        }

        System.out.println("正在上传图片: " + imagePath);
        System.out.println("目标API: " + apiUrl);
        System.out.println("使用模型编码: " + modelCode);

        try {
            // 构建multipart/form-data请求
            String boundary = "Boundary-" + UUID.randomUUID().toString();
            StringBuilder bodyBuilder = new StringBuilder();
            
            // 添加model_code字段
            bodyBuilder.append("--").append(boundary).append("\r\n")
                    .append("Content-Disposition: form-data; name=\"model_code\"\r\n")
                    .append("\r\n")
                    .append(modelCode).append("\r\n");
            
            // 添加file字段
            bodyBuilder.append("--").append(boundary).append("\r\n")
                    .append("Content-Disposition: form-data; name=\"file\"; filename=\"").append(imageFile.getName()).append("\"\r\n")
                    .append("Content-Type: image/jpeg\r\n")
                    .append("\r\n");
            
            // 读取文件内容
            byte[] fileContent = readFileContent(imageFile);
            
            // 构建完整请求体
            byte[] bodyPrefix = bodyBuilder.toString().getBytes(StandardCharsets.UTF_8);
            byte[] bodySuffix = ("\r\n--" + boundary + "--\r\n").getBytes(StandardCharsets.UTF_8);
            
            // 创建完整的请求体字节数组
            byte[] requestBody = new byte[bodyPrefix.length + fileContent.length + bodySuffix.length];
            System.arraycopy(bodyPrefix, 0, requestBody, 0, bodyPrefix.length);
            System.arraycopy(fileContent, 0, requestBody, bodyPrefix.length, fileContent.length);
            System.arraycopy(bodySuffix, 0, requestBody, bodyPrefix.length + fileContent.length, bodySuffix.length);
            
            // 构建请求
            HttpRequest request = HttpRequest.newBuilder()
                    .uri(URI.create(apiUrl))
                    .header("Content-Type", "multipart/form-data; boundary=" + boundary)
                    .POST(HttpRequest.BodyPublishers.ofByteArray(requestBody))
                    .build();
            
            // 发送请求
            HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
            
            // 检查响应状态
            if (response.statusCode() != 200) {
                System.out.println("请求失败，状态码: " + response.statusCode() + ", 响应内容: " + response.body());
                return null;
            }
            
            // 解析JSON响应
            try {
                return objectMapper.readValue(response.body(), DetectionResult.class);
            } catch (Exception e) {
                System.out.println("警告: 无法解析响应为JSON，原始响应内容: " + response.body());
                return null;
            }
            
        } catch (IOException e) {
            System.out.println("I/O错误: " + e.getMessage());
            e.printStackTrace();
            return null;
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            System.out.println("请求被中断: " + e.getMessage());
            e.printStackTrace();
            return null;
        } catch (Exception e) {
            System.out.println("发生错误: " + e.getMessage());
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 使用枚举类型上传图片进行检测
     * @param imagePath 图片文件路径
     * @param modelType 模型类型枚举
     * @return 检测结果对象
     */
    public DetectionResult uploadImageForDetection(String imagePath, ModelType modelType) {
        return uploadImageForDetection(imagePath, modelType.getCode());
    }

    /**
     * 打印检测结果
     * @param result 检测结果对象
     */
    public void printDetectionResult(DetectionResult result) {
        if (result == null) {
            System.out.println("没有有效的检测结果");
            return;
        }

        // 美化打印结果
        System.out.println("\n检测结果:");
        try {
            System.out.println(objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(result));
        } catch (Exception e) {
            System.out.println("无法格式化输出结果");
        }

        // 打印基本信息
        if (result.getOriginal_url() != null) {
            System.out.println("\n原始图片URL: " + result.getOriginal_url());
        }

        if (result.getDetected_url() != null) {
            System.out.println("检测结果URL: " + result.getDetected_url());
        }

        // 打印图片尺寸
        if (result.getImage_size() != null) {
            System.out.println("图片尺寸: " + result.getImage_size().getWidth() + "x" + result.getImage_size().getHeight());
        }

        // 打印使用的模型信息
        if (result.getModel_used() != null) {
            System.out.println("使用模型: " + result.getModel_used().getName() + " (" + result.getModel_used().getCode() + ")");
            if (result.getModel_used().isIs_fallback()) {
                System.out.println("提示: 由于指定模型不可用，系统自动使用了备选模型");
            }
        }

        // 打印消息
        if (result.getMessage() != null) {
            System.out.println("\n消息: " + result.getMessage());
        }

        // 打印检测到的目标
        if (result.getDetections() != null) {
            System.out.println("\n检测到的目标数量: " + result.getDetections().size());
            
            // 打印每个检测目标的详细信息
            for (int i = 0; i < result.getDetections().size(); i++) {
                DetectionResult.Detection detection = result.getDetections().get(i);
                System.out.println("\n目标 " + (i + 1) + ":");
                
                if (detection.getClazz() != null) {
                    System.out.println("  类别: " + detection.getClazz());
                }
                
                System.out.println("  置信度: " + String.format("%.2f", detection.getConfidence()));
                
                if (detection.getBbox() != null) {
                    DetectionResult.BoundingBox bbox = detection.getBbox();
                    System.out.println("  边界框: xmin=" + bbox.getXmin() + ", ymin=" + bbox.getYmin() + 
                            ", xmax=" + bbox.getXmax() + ", ymax=" + bbox.getYmax());
                }
            }
        }
    }

    /**
     * 检测图片并保存结果到JSON文件
     * @param imagePath 图片路径
     * @param modelCode 模型编码
     * @param saveJson 是否保存结果
     * @return 检测结果
     */
    public DetectionResult detectAndSaveResult(String imagePath, String modelCode, boolean saveJson) {
        // 调用API进行检测
        DetectionResult detectionResult = uploadImageForDetection(imagePath, modelCode);
        
        // 打印检测结果
        printDetectionResult(detectionResult);
        
        // 保存结果到JSON文件
        if (saveJson && detectionResult != null) {
            try {
                // 生成保存文件名
                File imageFile = new File(imagePath);
                String baseName = imageFile.getName().substring(0, imageFile.getName().lastIndexOf('.'));
                
                // 创建输出目录
                File outDir = new File("./detect_out");
                if (!outDir.exists()) {
                    outDir.mkdirs();
                }
                
                File jsonFile = new File(outDir, "detection_result_" + baseName + ".json");
                
                // 保存JSON文件
                objectMapper.writerWithDefaultPrettyPrinter().writeValue(jsonFile, detectionResult);
                
                // 根据模型类型显示不同的保存消息
                ModelType modelType = ModelType.fromCode(modelCode);
                if (modelType != null) {
                    System.out.println("\n" + modelType.getDescription() + "结果已保存到: " + jsonFile.getAbsolutePath());
                } else {
                    System.out.println("\n检测结果已保存到: " + jsonFile.getAbsolutePath());
                }
                
            } catch (Exception e) {
                System.out.println("保存结果失败: " + e.getMessage());
                e.printStackTrace();
            }
        }
        
        // 根据模型类型显示不同的完成消息
        ModelType modelType = ModelType.fromCode(modelCode);
        if (modelType != null) {
            System.out.println("\n" + modelType.getDescription().replaceAll("^\\d+", "").trim() + "完成");
        } else {
            System.out.println("\n检测完成");
        }
        
        return detectionResult;
    }

    /**
     * 使用枚举类型检测图片并保存结果
     * @param imagePath 图片路径
     * @param modelType 模型类型枚举
     * @param saveJson 是否保存结果
     * @return 检测结果
     */
    public DetectionResult detectAndSaveResult(String imagePath, ModelType modelType, boolean saveJson) {
        return detectAndSaveResult(imagePath, modelType.getCode(), saveJson);
    }

    /**
     * 默认保存结果的检测方法
     * @param imagePath 图片路径
     * @param modelCode 模型编码
     * @return 检测结果
     */
    public DetectionResult detectAndSaveResult(String imagePath, String modelCode) {
        return detectAndSaveResult(imagePath, modelCode, true);
    }

    /**
     * 使用枚举类型的默认保存结果检测方法
     * @param imagePath 图片路径
     * @param modelType 模型类型枚举
     * @return 检测结果
     */
    public DetectionResult detectAndSaveResult(String imagePath, ModelType modelType) {
        return detectAndSaveResult(imagePath, modelType, true);
    }

    /**
     * 读取文件内容为字节数组
     * @param file 文件对象
     * @return 文件内容字节数组
     * @throws IOException IO异常
     */
    private byte[] readFileContent(File file) throws IOException {
        try (InputStream is = new FileInputStream(file)) {
            byte[] buffer = new byte[(int) file.length()];
            int read = is.read(buffer);
            if (read != file.length()) {
                throw new IOException("文件读取不完整");
            }
            return buffer;
        }
    }
}